﻿using NL;
using NL.UI;
using NL.Web;
using System;
using System.Collections;
using System.IO;
using System.Net.Http;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Events;
using UnityEngine.PlayerLoop;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

namespace Miya.Hellow
{

    public class WELCOME : MonoBehaviour
    {

    

        public static string VERSION_REMOTE_DOMAIN = "";
        public static bool USINGHOTUPDATE = true;

        public static bool IS_WHITEBILL = true;

        //public static VersionInfo Version => _VersionInfoLocal;

        //static VersionInfo _VersionInfoLocal;

        //public static VersionInfo VersionRemote => _VersionInfoRemote;
        //static VersionInfo _VersionInfoRemote;



        /// 
        /// 
        /// Welcome 启动流程/
        /// 1. Welcome 获取版本信息....--> 访问根服务获取版本校验地址---->带上版本信息组成版本校验URL---->获取远端版本信息.判断是否需要更新...
        /// 
        /// 2.启动Updater节点执行版本校验+更新
        ///    
        /// 
        /// 3.等待Update完成下载( 程序集下载;首要资产下载;静默资产下载) 后..启动Hybrid.
        ///
        /// 
        /// 4.Hybrid初始化程序集清单..加载程序集...--->启动游戏 (sc_intro);
        ///


        //[Header("APP 根服务地址.. http://welcome.miya.fun/gameconfig?app=xxx&device=xxxxx")]
        //public string RootUrlDomain = $"http://welcome.miya.fun";

        [Header("版本校验服务域名")]
        public string VersionRemoteDomian;



        [Header("启动场景")]
        public string SCENE_NAME_INTRO = "sc_Intro";
        [Header("当无法完成版本校验的时候,是否可以直接跳过,进入游戏")]
        public bool SkipError = false;


        public Slider UI_UpdateProgress;
        public Text UI_ProgressText;

        [Header("用谁 展示加载中得提示")]
        public Tiper Mod_Tiper;
        Tiper _Tiper;

        public string Error;

        #region("Events")
        [Header("初始化")]
        public UnityEvent ActionForInit;
        [Header("完成")]
        public UnityEvent ActionForEnd;
        [Header("失败")]
        public UnityEvent ActionForError;

        [Header("解析版本信息")]
        public UnityEvent ActionForVersionInfoInit;

        [Header("解析远端版本信息")]
        public UnityEvent ActionForVersionInfoRomote;

        [Header("解析版本信息出错")]
        public UnityEvent ActionForVersionInfoError;

        [Header("解析版本信息结束")]
        public UnityEvent ActionForVersionInfoEnd;

        [Header("开始下载/更新")]
        public UnityEvent ActionForUpdateBegin;

        [Header("开始下载....")]
        public UnityEvent ActionForUpdating;

        [Header("开始下载完成")]
        public UnityEvent ActionForUpdateSuccess;

        [Header("开始下载失败")]
        public UnityEvent ActionForUpdateFaild;

        [Header("注入成功")]
        public UnityEvent ActionForHybridSuccess;

        [Header("注入失败")]
        public UnityEvent ActionForHybridFaild;
#endregion 


        public static bool Logable = true;
        public static void Log(string log) { if (!Logable) return; Debug.Log(log); }
        string VersionFile_Inner => Path.Combine($"{Application.streamingAssetsPath}", "version.info");

        string VersionFile_Outer => $"{Path.Combine($"{Application.persistentDataPath}", "version.info")}";

        string CatalogFile_Outer=> $"{Path.Combine($"{Application.persistentDataPath}",Addressables.StreamingAssetsSubFolder, "catalog.json")}";

        string __State;
        string State
        {
            get { return __State; }
            set { __State = value; gameObject.INFOSet("state", __State); }
        }


        public bool VersionServerEnable = true;



        NLInfo Info;
        void Awake()
        {
            ActionForInit?.Invoke();

            gameObject.INFOSet("state", "");
            

            if (UI_UpdateProgress != null)                UI_UpdateProgress.gameObject.SetActive(false);
            if (UI_ProgressText != null)                UI_ProgressText.gameObject.SetActive(false);
            Error = ""; State = "Initializating";

            gameObject.INFOSet("size_all", 0);            gameObject.INFOSet("size_download", 0);

            if (Mod_Tiper != null)                _Tiper = GameObject.Instantiate<Tiper>(Mod_Tiper,transform);

            if (_Tiper != null) _Tiper.Close();

        }

              
        IEnumerator Start()
        {

            Log($"[WELCOME.Start]:.........................................");

            //////
            /// 111111.................本地版本信息获取.....
            ////// 
            {
                State = "VersionLoad";
                if (_Tiper != null) _Tiper.Show();
                yield return VERSION.LoadAndWaitEnd(gameObject);

                VERSION.BindInfoTo(gameObject);

                if (!string.IsNullOrEmpty(VERSION.LoadError))
                {   //校验出错
                    _LogFailed(VERSION.LoadError); yield break;
                }

                if (_Tiper != null) _Tiper.Close();
                Log($"[WELCOME.Start]:_VersionInfoLocal={VERSION.Version.ToString(';')}");
            }

            ////
            ///22222222...............初始化 远程版本校验..................
            ////

            //是否使用静态变量得 版本校验地址..
            if (!string.IsNullOrEmpty(VERSION_REMOTE_DOMAIN))
                VERSION.SetVersionRemote(VERSION_REMOTE_DOMAIN);
            else
                VERSION.SetVersionRemote(VersionRemoteDomian);



            //给HTTP设置 主域名...
            HTTP.DOMAIN = VERSION.RemotePath;


            if (VERSION.QuickLaunch)
            {
                OverloadAndGOGO(); yield break;
            }

            
            Try();


        }

        int RETRY_COUNT = 0;
        void Try()
        {

            if (RETRY_COUNT++ > 10)
            {
                // 初始化失败.是否重试..
                ShowErrorBox(100, r =>
                {
                    if (r == UIWindowResult.wrOK)
                    {
                        RETRY_COUNT = 0;
                        _DoCheckAndUpdate();
                    }
                    else
                    {
                        Application.Quit();
                    }

                });
            }
            else
            {
                _DoCheckAndUpdate();
            }
        }

        void _DoCheckAndUpdate()
        {
            StopAllCoroutines();
            StartCoroutine(_CheckAndUpdater((error) =>
            {
                if (error > 0)
                {
                    //弹出错误提示.确定后继续请求
                    ShowErrorBox(error, r =>
                    {
                        Try();

                    }, UIButtonsModel.bmOk);
                }
                else
                {
                    OverloadAndGOGO();
                }
            }));
        }



        VersionInfo _VersionInfoLocal, _VersionInfoRemote;
        Updater _NowUpdater;
        IEnumerator _CheckAndUpdater(Action<int> on)
        {
			Debug.Log("[WELCOME._CheckAndUpdater]:开始检查更新");
            ActionForVersionInfoInit?.Invoke();

            if (_NowUpdater != null && _NowUpdater.gameObject.activeInHierarchy)
            {
                GameObject.Destroy(_NowUpdater.gameObject);
            }

            _VersionInfoLocal = VERSION.Version;
            string remote_path = VERSION.RemotePath;
            {

                ////
                //3.拼接 版本校验服务URL........访问版本校验服务........ 注意版本信息 使用 a.b.... DOMAIN/渠道/平台/主版本号
                ////



                if (_Tiper != null) _Tiper.Show();

                /// 获取版本服务文件地址...
                var QQ = TextFileRequest.Request($"{remote_path}/_version.info");
				Debug.Log("[WELCOME._CheckAndUpdater]:获取版本服务文件地址...{remote_path}/_version.info");
                
                yield return QQ.WaitEnd();


                if (_Tiper != null) _Tiper.Close();

                if (string.IsNullOrEmpty(QQ.Result))
                {
                    //访问版本校验服务出错
                    _LogFailed($"访问版本校验服务出错@{RETRY_COUNT} VersionServerNone:@{QQ.Url}");

                    ActionForVersionInfoError?.Invoke();

                    yield return new WaitForSeconds(1);
                    on?.Invoke(101);
                    yield break;
                }
                else
                {
                    //初始化 远端版本数据  

                    _VersionInfoRemote = new VersionInfo(QQ.Result, '\n');
                    Log($"[WELCOME.Start]:初始化远端版本信息 _VersionInfoRemote@{remote_path} \n  {_VersionInfoRemote}");
                    //初始化AddressablePro... 设置路径转换器，转换成自定义路径

                    AddressablePro.Init(remote_path);


                    ActionForVersionInfoRomote?.Invoke();
					Debug.Log("[WELCOME._CheckAndUpdater]:初始化远端版本信息 _VersionInfoRemote@{remote_path} \n  {_VersionInfoRemote}");
                }
            }

            ActionForVersionInfoEnd?.Invoke();

            // 需要商店更新app得...不能热更
            if (_VersionInfoRemote.AssmblyCode != _VersionInfoLocal.AssmblyCode)
            {
      

                yield return new WaitForSeconds(1);
                ShowErrorBox(666, r =>
                {
                   if(r== UIWindowResult.wrOK)
                        Application.OpenURL(VERSION.AppUrl);
                    Application.Quit();
                },UIButtonsModel.bmOk);
                yield break;
            }



            
            ////
            //远端版本比本地版本 大大大大大大大大大大大大? 
            ////
            {

                if (_VersionInfoRemote > _VersionInfoLocal )
                {
                    gameObject.INFOSet("state", "Updating");

                    Log($"[WELCOME.Start]:远端版本:{_VersionInfoRemote.Full}  >   本地版本:{_VersionInfoLocal.Full}");

          

                    

                    //版本校验+补丁下载
                    _NowUpdater = new GameObject("~Updater").AddComponent<Updater>().Set(remote_path)
                        .WaitError(w =>
                        {
                            _LogFailed(w.Error);

                            ActionForUpdateFaild?.Invoke();

                            // 多次下载失败 重试>10次. 重新尝试..还是退出APP
                            if(w.ErrorCode==200)
                            {
                                ShowErrorBox(200, r =>
                                {
                                    if (r == UIWindowResult.wrOK)
                                    {
                                        _DoCheckAndUpdate();
                                    }
                                    else
                                    {
                                        Application.Quit();
                                    }

                                });
                            }

                        }).WaitPrepared(w =>
                        {
                            ActionForUpdateBegin?.Invoke();
                            gameObject.INFOSet("size_all", w.SizeAllInMB.ToString("N"));
                            gameObject.INFOSet("size_download", 0);

                        }).WaitUpdate(w =>
                        {
                            gameObject.INFOSet("size_download", w.SizeDownLoadInMB.ToString("N"));
                            if (UI_UpdateProgress != null)
                            {
                                UI_UpdateProgress.gameObject.SetActive(true);
                                UI_UpdateProgress.value = w.Progress;
                            }
                            if (UI_ProgressText != null)
                            {
                                UI_ProgressText.gameObject.SetActive(true);
                                UI_ProgressText.text = w.Progress.ToString("0.#%");
                            }

                        }, gameObject);

                    

                    //等待下载首要资产...
                    yield return _NowUpdater.UntilPrimaryUpdated();

                    ActionForUpdateSuccess?.Invoke();

                    ////更新完成保存版本信息..........................
                    ///
                    /// 
                    /// 
                    /// 
                    ///
                    //gameObject.INFOSet("version", _VersionInfoRemote["version"]);
                    //gameObject.INFOSet("version", _VersionInfoRemote["buildnum"]);
                    gameObject.INFOAdd(_VersionInfoRemote);
                    //保存版本信息..
                    File.WriteAllText(VersionFile_Outer, _VersionInfoRemote.ToString('\n'));


                    // 次要资产可以慢慢下载....
                    //等待下载必须的内容
                    //yield return update.UntilComplete();

                    yield return 0;


                    //更新版本信息
                    VERSION.SetHotVersion(_VersionInfoRemote);

                    yield return 1;

                    _LogSuccess();

                    _DoCheckAndUpdate(); //二次检查...
                }
                else
                {
                    try
                    {
                        Log($"[WELCOME.Start]: 远端版本:{_VersionInfoRemote.Basic} <= 本地版本:{_VersionInfoLocal.Basic}");
                    }catch
                    {

                    }
                    on?.Invoke(0);

                }
            }
        }


        Box _MeesageBox;
        void _LogFailed(string error)
        {
            Error = State = error;
            Log($"[WELCOME._Failed]:Error={Error}");

        }
        void _LogSuccess()
        {
            Error = ""; State = "Success";

            Log($"[WELCOME._Success]:..........................");

      
        }




       public void OverloadAndGOGO()
        {
            StopAllCoroutines();
            StartCoroutine(_OverLoader());
        }
        /// <summary>
        /// 开始启动
        /// 1....Addressable 重定位...(使用沙盒得装配清单和资产包)
        /// 2....程序集注入....
        /// </summary>
        /// <returns></returns>
        IEnumerator _OverLoader()
        {
            State = "Launching";

            WELCOME.Log($"[WELCOM._Launcher]:..........................");

            //Addressable 重定位...(使用沙盒得装配清单和资产包)????
            if (File.Exists(CatalogFile_Outer))
            {
                WELCOME.Log($"[WELCOM._Launcher]:.....File.Exists(({CatalogFile_Outer})");
                string textall=   File.ReadAllText(CatalogFile_Outer);

                // 替换成新的Catalog
                if (!string.IsNullOrEmpty(textall))
                {
                    var data = JsonUtility.FromJson(textall, typeof(ContentCatalogData)) as ContentCatalogData;

                    var lacator = data?.CreateLocator();
                    if (lacator != null)
                    {
                        Addressables.ClearResourceLocators();
                        Addressables.AddResourceLocator(lacator);
                        WELCOME.Log($"[WELCOM._Launcher]:Addressables.AddResourceLocator().............END");
                    }
                }
            }
            else
            {
                WELCOME.Log($"[WELCOM._Launcher]:.....No File:({CatalogFile_Outer}");
            }


            WELCOME.Log($"[WELCOM._Launcher]:Hybrid.............");

            //启动 Hybrid
            yield return new GameObject("~Hybrid").AddComponent<Hybrid>().WaitPrepared((w) =>
            {
       
            }).WaitError(w=>
            {
                //重载程序集失败 弹窗提示 重新更新流程
                ActionForHybridFaild?.Invoke();
                ShowErrorBox(300, r =>
                {
                    _DoCheckAndUpdate();
                }, UIButtonsModel.bmOk);

            }).WaitEnd();

            WELCOME.Log($"[WELCOM._Launcher]:Hybrid.............END");


            yield return new WaitForSeconds(0.2f);


         
            ActionForHybridSuccess?.Invoke();

            _GOGO();
        }

        void _GOGO()
        {
            Addressables.LoadSceneAsync(SCENE_NAME_INTRO, UnityEngine.SceneManagement.LoadSceneMode.Single);
            WELCOME.Log($"[WELCOM._Launcher]:LoadSceneAsync({SCENE_NAME_INTRO}).............");
        }


        private void OnDestroy()
        {
            ActionForEnd?.Invoke();
        }



        //static Box _MessageBox;
        public static Box ShowErrorBox(int error, Action<UIWindowResult> onclose, UIButtonsModel bm = UIButtonsModel.bmOkCancel)
        {
            string title = "TIPS";

            string content = "";// 默认错误提示

            switch (error)
            {

                case 100: content = $"Initialization failed.. Do you want to try again?"; break;  //重试10次以上.重试还是退出..初始化失败.是否重试..

                case 101: content = $"Initialization failed.."; break;  //远端版本信息校验出错..

                case 666: content = $"Initialization failed, please jump to the store to download the latest client！"; break;   //不能热更需要跳转商店更新


                case 200: content = $"Resource download failed. Do you want to try again?"; break;  //下载:重试10次以上.重试还是退出..初始化失败.是否重试..
                //case 201: content = $"[UPDATE_ERROR_201]"; break;  //下载清单分析出错

                //case 300: content = $"[UPDATE_ERROR_300]"; break;  //重载程序集失败

                default: content = $"The game exception is being processed, please try again later or re-download the latest client."; break;       // 默认错误提示

            }





            //if (_MessageBox == null)
            //    _MessageBox = UI.ShowBox(title, content, bm);
            //else
            //    _MessageBox.Show(title, content, bm);
            var box = UI.ShowBox(title, content, bm);
            if (box == null)
            {
                onclose?.Invoke(UIWindowResult.wrCancel);
            }
            else
            {
                box?.WaitClose((w, r) =>
                {
                    onclose?.Invoke(r);
                });
            }


            return box;
        }
    }
}

